/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.dtgenerator.core.codeRule;

import com.inspur.edp.bef.bizentity.GspBizEntityObject;
import com.inspur.edp.bef.spi.entity.CodeRuleInfo;
import com.inspur.edp.caf.generator.baseInfo.ParameterInfo;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.caf.generator.utils.ExpressionUtils;
import com.inspur.edp.cef.designtime.api.IGspCommonField;
import com.inspur.edp.das.commonmodel.IGspCommonElement;
import com.inspur.edp.das.commonmodel.collection.GspElementCollection;
import com.inspur.edp.das.commonmodel.entity.element.GspBillCodeGenerateOccasion;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;

public class AfterCreateMethodGenerator extends ClassMethodGenerator {
    private GspBizEntityObject beObject;

    public AfterCreateMethodGenerator(GspBizEntityObject beObject) {
        this.beObject = beObject;
    }


    private static final String ParamACDic = "acDic";


    protected boolean getIsOverride() {
        return true;
    }


    protected ArrayList<Modifier.ModifierKeyword> getAccessModifiers() {
        return new ArrayList(
                Arrays.asList(new Modifier.ModifierKeyword[]{Modifier.ModifierKeyword.PUBLIC_KEYWORD}));
    }


    protected String getMethodName() {
        return "afterCreate";
    }


    protected ArrayList<ParameterInfo> getParameterCollection() {
        return new ArrayList();
    }


    protected TypeInfo getReturnType() {
        return getDicType();
    }


    private TypeInfo getDicType() {
        TypeInfo typeInfo = new TypeInfo(HashMap.class);
        typeInfo.setIsParameterizedType(Boolean.valueOf(true));
        typeInfo.getArguments().add(new TypeInfo(String.class));
        addImport(CodeRuleInfo.class.getTypeName());
        typeInfo.getArguments().add(new TypeInfo(CodeRuleInfo.class));

        return typeInfo;
    }


    protected Block buildMethodBody() {
        Block block = this.ast.newBlock();
        block.statements().add(getCreateDicStatement());
        getAfterCreateContent(block);

        block.statements().add(getReturnStatement());
        return block;
    }

    private Statement getCreateDicStatement() {
        VariableDeclarationFragment frag = this.ast.newVariableDeclarationFragment();
        frag.setName(this.ast.newSimpleName("acDic"));
        ClassInstanceCreation creation = this.ast.newClassInstanceCreation();
        creation.setType(getDicType().getType(this.ast));
        frag.setInitializer(creation);
        VariableDeclarationStatement statement = this.ast.newVariableDeclarationStatement(frag);
        statement.setType(getDicType().getType(this.ast));
        return statement;
    }

    private ReturnStatement getReturnStatement() {
        ReturnStatement statement = this.ast.newReturnStatement();
        statement.setExpression(this.ast.newSimpleName("acDic"));
        return statement;
    }

    private HashMap<String, CodeRuleInfo> getCodeRuleRecord() {
        HashMap<String, CodeRuleInfo> dic = new HashMap<String, CodeRuleInfo>();

        GspElementCollection elements = this.beObject.getContainElements();

        for (IGspCommonField item : elements) {

            IGspCommonElement element = (IGspCommonElement) item;
            if (element.getBillCodeConfig().getCanBillCode() &&
                    element.getBillCodeConfig().getCodeGenerateOccasion() == GspBillCodeGenerateOccasion.CreatingTime) {

                CodeRuleInfo tempVar = new CodeRuleInfo();
                tempVar.setCodeRuleId(element.getBillCodeConfig().getBillCodeID());
                dic.put(element.getLabelID(), tempVar);
            }
        }


        return dic;
    }

    private void getAfterCreateContent(Block block) {
        HashMap<String, CodeRuleInfo> dic = getCodeRuleRecord();
        addImport(CodeRuleInfo.class.getTypeName());
        for (String key : dic.keySet()) {

            String varName = key + "Info";
            block.statements().add(getCreateInfoStatement(varName));
            block.statements().add(getSetRuleIdStatement(varName, ((CodeRuleInfo) dic.get(key)).getCodeRuleId()));
            block.statements().add(getSetDicStatement(key, varName));
        }
    }


    private Statement getCreateInfoStatement(String varName) {
        VariableDeclarationFragment frag = this.ast.newVariableDeclarationFragment();
        frag.setName(this.ast.newSimpleName(varName));
        ClassInstanceCreation creation = this.ast.newClassInstanceCreation();
        creation.setType((new TypeInfo(CodeRuleInfo.class)).getType(this.ast));
        frag.setInitializer(creation);
        VariableDeclarationStatement statement = this.ast.newVariableDeclarationStatement(frag);
        statement.setType((new TypeInfo(CodeRuleInfo.class)).getType(this.ast));
        return statement;
    }

    private Statement getSetRuleIdStatement(String varName, String ruleId) {
        MethodInvocation invocation = ExpressionUtils.getMethodInvocation(this.ast, varName, "setCodeRuleId");
        invocation.arguments().add(ExpressionUtils.getStringLiteral(this.ast, ruleId));
        return this.ast.newExpressionStatement(invocation);
    }

    private Statement getSetDicStatement(String key, String ruleParamName) {
        MethodInvocation invocation = ExpressionUtils.getMethodInvocation(this.ast, "acDic", "put");
        invocation.arguments().add(ExpressionUtils.getStringLiteral(this.ast, key));
        invocation.arguments().add(this.ast.newSimpleName(ruleParamName));
        return this.ast.newExpressionStatement(invocation);
    }
}
